package cau.se.project.unittest;

import static org.easymock.EasyMock.createMock;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

import java.util.Enumeration;

import javax.swing.tree.TreeNode;

import org.junit.Before;
import org.junit.Test;

import cau.se.project.data.CLSXGroup;
import cau.se.project.data.DSMRow;
import cau.se.project.data.method.RowControl;

public class CLSXGroupTest {
	private CLSXGroup parentGroup;
	private CLSXGroup clsxGroup;
	private RowControl dsmRow;
	
	@Before
	public void setUp() throws Exception {
		parentGroup = new CLSXGroup("ParentGroup");
		clsxGroup = new CLSXGroup("TestGroup");
		dsmRow = new DSMRow("TestRow");
	}

	@Test
	public void testSetDependency() {
		assertTrue(this.clsxGroup.getDepenencyList().isEmpty());
		this.clsxGroup.setDependency(dsmRow);
		
		assertThat(this.clsxGroup.getDepenencyList().get(0), is(dsmRow));
	}

	@Test
	public void testGetChildAt() throws Exception {
		this.clsxGroup.insertGroupMember(dsmRow, null);
		assertThat((RowControl)this.clsxGroup.getChildAt(0), is(dsmRow));
	}
	
	@Test(expected=IndexOutOfBoundsException.class)
	public void testGetChildAtWithException() {
		this.clsxGroup.getChildAt(0);
	}

	@Test
	public void testGetChildCount() throws Exception {
		assertThat(this.clsxGroup.getChildCount(), is(0));
		
		this.clsxGroup.insertGroupMember(dsmRow, null);
		
		assertThat(this.clsxGroup.getChildCount(), is(1));
	}

	@Test
	public void testGetIndex() throws Exception {
		assertThat(this.clsxGroup.getIndex(null), is(-1));
		this.clsxGroup.insertGroupMember(dsmRow, null);
		
		assertThat(this.clsxGroup.getIndex(dsmRow), is(0));
	}

	@Test
	public void testGetAllowsChildren() {
		assertTrue(this.clsxGroup.getAllowsChildren());
	}

	@Test
	public void testIsLeaf() {
		assertFalse(this.clsxGroup.isLeaf());
	}

	@Test
	public void testChildren() throws Exception {
		Enumeration<TreeNode> mockChildren = createMock(Enumeration.class);
		assertThat(this.clsxGroup.children().hasMoreElements(), is(mockChildren.hasMoreElements()));
		
		this.clsxGroup.insertGroupMember(dsmRow, null);
		
		assertTrue(this.clsxGroup.children().hasMoreElements());
	}

	@Test
	public void testCLSXGroup() {
		CLSXGroup testGroup = new CLSXGroup("TestGroup");
		assertThat(testGroup.getName(), is("TestGroup"));
		assertThat(testGroup.getChildCount(), is(0));
		assertTrue(testGroup.getAllowsChildren());
		assertTrue(testGroup.getDepenencyList().isEmpty());
	}

	@Test
	public void testAddGroupMember() throws Exception {
		assertThat(this.clsxGroup.getChildCount(), is(0));
		
		this.clsxGroup.addGroupMember(dsmRow);
		
		assertThat(this.clsxGroup.getChildCount(), is(1));
	}

	@Test
	public void testInsertGroupMember() throws Exception {
		assertThat(this.clsxGroup.getChildCount(), is(0));
		
		this.clsxGroup.insertGroupMember(dsmRow, null);

		assertThat((RowControl)this.clsxGroup.getChildAt(0), is(dsmRow));
	}
	
	@Test(expected=Exception.class)
	public void testInsertGroupMemberWithException() throws Exception {
		this.clsxGroup.insertGroupMember(dsmRow, null);
		this.clsxGroup.insertGroupMember(dsmRow, null);
	}
	
	@Test
	public void testRemoveGroupMember() throws Exception {
		this.clsxGroup.insertGroupMember(dsmRow, null);
		assertThat((RowControl)clsxGroup.getChildAt(0), is(dsmRow));
		
		this.clsxGroup.removeGroupMember(dsmRow);
		assertTrue(dsmRow.getDepenencyList().isEmpty());
		
	}
	
	@Test
	public void testFindRowByName() throws Exception {
		assertNull(this.clsxGroup.findRowByName("TestRow"));

		this.clsxGroup.addGroupMember(dsmRow);
		
		assertThat((RowControl)this.clsxGroup.findRowByName("TestRow"), is(this.dsmRow));
	}
	
	@Test
	public void testIsDependencyToChild() throws Exception {
		RowControl anotherRow = new DSMRow("AnotherRow");
		assertFalse(this.clsxGroup.isDependencyToChild(anotherRow));
		
		anotherRow.setDependency(this.dsmRow);
		this.clsxGroup.addGroupMember(dsmRow);

		assertTrue(this.clsxGroup.isDependencyToChild(anotherRow));
	}
	
	@Test
	public void testIsDependencyToChildWithParentGroup() throws Exception {
		this.dsmRow.setDependency(this.clsxGroup);
		this.clsxGroup.addGroupMember(dsmRow);
		
		this.parentGroup.addGroupMember(this.clsxGroup);
		
		assertTrue(this.parentGroup.isDependencyToChild(dsmRow));
	}
}
